/***********************************************************************************************************************
 * ############################################# Application AdewebLite #############################################
 * AdewebLite Android est une application permettant de consulter des emplois du temps fournis par l'université UHP
 * avec ou sans connexion internet (informations gardées en mémoire à chaque synchronisation). Et utilisant la web
 * API ADE pour collecter les données.
 * @author Andrianjafintrimo Victor, Zanette Sébastien
 * 
 * Basée sur l'application du même nom, utilisant le flux RSS (données à traiter), de :
 * @author Schnell Michaël, Zanette Sébastien
 * **********************************************************************************************************************
 */

package fr.ul.ade.prime.model;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

/**
 * Structure pour un cour. Un cour à un nom, une salle, un lieu, un groupe, un
 * professeur et un type associé Contient un ensemble de fonctions permettant de
 * créer, modifier, obtenir des informations sur un cours
 * 
 * @author Zanette Sébastien,
 * @author Andrianjafintrimo Victor
 */
public class Lesson implements Comparable<Lesson>, Parcelable {

	private static final String PRINT_FORMAT = "ID : %s\nGuid : %s\nCours : '%s'\nNom de l'EDT associé : '%S'\nType :" //$NON-NLS-1$
			+ " %s\nSalle(s) : '%s'\nGroupes : '%s'\nEnseignant(s) : '%s'\nHeure : '%s'\nCouleur : '%s'\nNote : '%s'\nDeleted: %b"; //$NON-NLS-1$

	public static final int NOT_DELETED = 0;
	public static final int DELETED = 1;

	private long lessonId;
	private String title;
	private String date;
	private String startHour;
	private String endHour;
	private long scheduleId;
	private LessonType type;
	private int change;
	private String rooms;
	private String groups;
	private String teachers;
	private String color;
	private String note;
	private String created;
	private Date startDateTime;
	private String guid;
	private LessonHistory history;
	private boolean deleted;
	// TODO Transform change into an enum
	// Niveau de changement d'un emploi du temps
	public static final int NO_CHANGE = 0;
	public static final int LITTLE_CHANGE = 1;
	public static final int BIG_CHANGE = 2;

	public Lesson(long lessonId, String title, String date, String startHour,
			String endHour, long scheduleId, LessonType type, int change,
			String room, String groups, String teacher, String color,
			String note, String created) {
		this();
		this.lessonId = lessonId;
		this.title = title;
		this.date = date;
		this.startHour = startHour;
		this.endHour = endHour;
		this.scheduleId = scheduleId;
		this.type = type;
		this.change = change;
		this.rooms = room;
		this.groups = groups;
		this.teachers = teacher;
		this.color = color;
		this.note = note;
		this.created = created;
		this.startDateTime = null;
	}

	public Lesson(String title, String date, String startHour, String endHour,
			long scheduleId, LessonType type, int change, String room,
			String groups, String teacher, String color, String note,
			String created) {
		this();
		this.title = title;
		this.date = date;
		this.startHour = startHour;
		this.endHour = endHour;
		this.scheduleId = scheduleId;
		this.type = type;
		this.change = change;
		this.rooms = room;
		this.groups = groups;
		this.teachers = teacher;
		this.color = color;
		this.note = note;
		this.created = created;
		this.startDateTime = null;
	}

	/**
	 * Permet de construire une {@code Lesson} à partir d'une serialisation
	 * 
	 * @param in
	 *            objet parcelable(=serialisable) contenant les informations du
	 *            cours
	 */
	public Lesson(Parcel in) {
		this(in.readLong(), // lesson id
				in.readString(), // title
				in.readString(), // date
				in.readString(), // startHour
				in.readString(), // endHour
				in.readLong(), // schedule id
								// lesson type
				LessonType.valueOf(in.readString()), in.readInt(), // change
																	// date
				in.readString(), // rooms
				in.readString(), // groups
				in.readString(), // teachers
				in.readString(), // color
				in.readString(), // note
				in.readString()); // created
		// Guid & history
		this.guid = in.readString();
		this.history = in.readParcelable(this.getClass().getClassLoader());
	}// Lesson(Parcel)

	/**
	 * Constructeur vide de la classe {@code Lesson}
	 */
	public Lesson() {
		super();
		this.guid = ""; //$NON-NLS-1$
		this.history = null;
	}

	public boolean isDeleted() {
		return this.deleted;
	}

	public void setDeleted(boolean deleted) {
		this.deleted = deleted;
	}

	/**
	 * @param history
	 *            the history to set
	 */
	public void setHistory(LessonHistory history) {
		this.history = history;
	}

	/**
	 * @param history
	 *            the history to set
	 */
	public void setHistory(Lesson history) {
		this.setHistory(new LessonHistory(history));
	}

	/**
	 * @return the history
	 */
	public LessonHistory getHistory() {
		return this.history;
	}

	/**
	 * @return the guid
	 */
	public String getGuid() {
		return this.guid;
	}

	/**
	 * @param guid
	 *            the guid to set
	 */
	public void setGuid(String guid) {
		this.guid = guid;
	}

	/**
	 * Permet de changer les groupes d'une {@code Lesson}
	 * 
	 * @param groups
	 *            nouveau groupes du cours
	 */
	public void setGroups(String groups) {
		this.groups = groups;
	}

	/**
	 * Permet de changer l'id d'une {@code Lesson}
	 * 
	 * @param lessonId
	 *            nouvel id du cours
	 */
	public void setLessonId(long lessonId) {
		this.lessonId = lessonId;
	}

	/**
	 * Permet de changer la salle d'une {@code Lesson}
	 * 
	 * @param room
	 *            nouvelle salle du cours
	 */
	public void setRoom(String room) {
		this.rooms = room;
	}

	/**
	 * Permet de changer le nom de l'emploi du temps associé à une
	 * {@code Lesson}
	 * 
	 * @param scheduleId
	 *            nouvel emploi du temps
	 */
	public void setScheduleId(long scheduleId) {
		this.scheduleId = scheduleId;
	}

	/**
	 * Permet de changer les professeurs d'une {@code Lesson}
	 * 
	 * @param teacher
	 *            nouveaux professeurs du cours
	 */
	public void setTeachers(String teacher) {
		this.teachers = teacher;
	}

	/**
	 * Permet de changer la date et l'heure d'une {@code Lesson}
	 * 
	 * @param time
	 *            nouvelles date et heure du cours
	 */
	public void setTime(String date, String startHour, String endHour) {
		this.date = date;
		this.startHour = startHour;
		this.endHour = endHour;
		this.startDateTime = null;
	}

	/**
	 * Permet de changer la date de création d'une {@code Lesson}
	 * 
	 * @param created
	 *            nouvelle date de création
	 */
	public void setCreated(String created) {
		this.created = created;
	}

	/**
	 * Permet de changer l'intitulé d'une {@code Lesson}
	 * 
	 * @param title
	 *            nouvelle intitulé du cours
	 */
	public void setTitle(String title) {
		this.title = title;
	}

	/**
	 * Permet de changer le type d'une {@code Lesson}
	 * 
	 * @param type
	 *            nouveau type du cours
	 */
	public void setType(LessonType type) {
		this.type = type;
	}

	/**
	 * Permet de changer l'importance d'un changement d'une {@code Lesson}
	 * 
	 * @param change
	 *            nouvelle importance de changement
	 */
	public void setChange(int change) {
		this.change = change;
	}

	/**
	 * Positionne la valeur du champ color à la valeur donnée en parmètre
	 * 
	 * @param color
	 *            couleur d'affichage du cours
	 */
	public void setColor(String color) {
		this.color = color;
	}

	/**
	 * Positionne la valeur du champ note à la valeur donnée en parmètre
	 * 
	 * @param note
	 *            du cours
	 */
	public void setNote(String note) {
		this.note = note;
	}

	/**
	 * Retourne la valeur du champ groups
	 * 
	 * @return les groupes d'un cours
	 */
	public String getGroups() {
		return this.groups;
	}

	/**
	 * Retourne la valeur du champ lessonId
	 * 
	 * @return l'id du cours
	 */
	public long getLessonId() {
		return this.lessonId;
	}

	/**
	 * Retourne la valeur du champ rooms
	 * 
	 * @return la salle du cours
	 */
	public String getRoom() {
		return this.rooms;
	}

	/**
	 * Retourne la valeur du champ schedule
	 * 
	 * @return l'emploi du temps du cours
	 */
	public long getScheduleId() {
		return this.scheduleId;
	}

	/**
	 * Retourne la valeur du champ teacher
	 * 
	 * @return les profresseurs liés au cours
	 */
	public String getTeacher() {
		return this.teachers;
	}

	/**
	 * Retourne la valeur du champ time
	 * 
	 * @return l'heure du cours
	 */
	public String getDate() {
		return this.date;
	}

	public String getStartHour() {
		return this.startHour;
	}

	public String getEndHour() {
		return this.endHour;
	}

	/**
	 * Retourne la valeur du champ created
	 * 
	 * @return la date de création du cours
	 */
	public String getCreated() {
		return this.created;
	}

	/**
	 * Retourne la valeur du champ title
	 * 
	 * @return l'intitullé du cours
	 */
	public String getTitle() {
		return this.title;
	}

	/**
	 * 
	 * Retourne la valeur du champ type
	 * 
	 * @return le type du cours
	 */
	public LessonType getType() {
		return this.type;
	}

	/**
	 * Retourne la valeur du champ change
	 * 
	 * @return statut de changement d'un cours
	 */
	public int getChange() {
		return this.change;
	}

	/**
	 * Retourne la valeur du champ color
	 * 
	 * @return la couleur d'affichage du cours
	 */
	public String getColor() {
		return this.color;
	}

	/**
	 * Retourne la valeur du champ note
	 * 
	 * @return note du cours
	 */
	public String getNote() {
		return this.note;
	}

	/**
	 * Retourne une chaîne de caractère avec les informations sur un cours
	 * 
	 * @return String contenant les informtion d'une {@code Lesson}
	 */
	@Override
	public String toString() {
		return String.format("[%s,%s]%s - %s %s-%s : %s",
				this.lessonId,
				this.guid,
				this.title,
				this.date,
				this.startHour,
				this.endHour,
				this.rooms);
		// return String.format(PRINT_FORMAT,
		// Long.valueOf(this.lessonId),
		// this.guid,
		// this.title,
		// Long.valueOf(this.scheduleId),
		// this.type,
		// this.rooms,
		// this.groups,
		// this.teachers,
		// this.date,
		// this.color,
		// this.note);
	}

	/**
	 * Permet de comparer la date de deux cours
	 * 
	 * @param another
	 *            {@code Lesson} à comparer avec l'instance actuelle
	 * @return un nombre positif l'instance actuelle a une date supérieur, 0 si
	 *         les deux dates sont égales, un nombre négatif sinon
	 */
	@Override
	public int compareTo(Lesson another) {
		Date start = this.getStartDateTime();
		Date end = another.getStartDateTime();
		// return this.time - another.time ;
		return start.compareTo(end);
	}// compareTo(Lesson)

	/**
	 * Permet de construire la date d'un cours au bon format (JJ/MM/AAAA)
	 */
	protected void buildDate() {
		// // Time representation example : 20/01/2012 10h00 - 12h00
		// StringBuilder s = new StringBuilder(this.time);
		// // Extract the beginning : 20/01/2012 10h00
		//		int pos = s.indexOf("-"); //$NON-NLS-1$
		// while ((pos > 0) && ((s.charAt(pos) < '0') || ('9' < s.charAt(pos))))
		// {
		// pos--;
		// }// while
		// s = new StringBuilder(s.substring(0, pos + 1));
		// try {
		//			this.date = new SimpleDateFormat("yyyy/MM/dd HH:mm").parse(s.toString()); //$NON-NLS-1$
		//			//			Log.i("buildate", "BuildDate : " + this.date); //$NON-NLS-1$ //$NON-NLS-2$
		// } catch (ParseException e) {
		//			Log.d("Lesson", String.format( //$NON-NLS-1$
		//					"Could not parse date '%s'", s.toString()), //$NON-NLS-1$
		// e) ;
		// }// try
		StringBuilder s = new StringBuilder(this.date).append(this.startHour);
		try {
			this.startDateTime = new SimpleDateFormat("yyyy/MM/ddHH:mm")
					.parse(s.toString());
		} catch (ParseException e) {
			Log.d("Lesson", String.format( //$NON-NLS-1$
			"Could not parse date '%s'",
					s.toString()), //$NON-NLS-1$
					e);
		}// try
	}

	/**
	 * Retourne la date d'un cours si le champ date n'est pas null, sinon on
	 * fait appel à buildDate()
	 * 
	 * @return la date d'un cours
	 */
	public Date getStartDateTime() {
		if (this.startDateTime == null) {
			this.buildDate();
		}// if
		return this.startDateTime;
	}// getDate()

	/**
	 * {@inheritedDoc}
	 */
	@Override
	public int describeContents() {
		return 0;
	}

	/**
	 * Ecrit les informarions d'une {@code Lesson} dans une structure de données
	 * 
	 * @param parcel
	 * @param flags
	 *            permet d'ajouter éventuellement des options
	 */
	@Override
	public void writeToParcel(Parcel parcel, int flags) {
		parcel.writeLong(this.lessonId);
		parcel.writeString(this.title);
		parcel.writeString(this.date);
		parcel.writeString(this.startHour);
		parcel.writeString(this.endHour);
		parcel.writeLong(this.scheduleId);
		parcel.writeString(this.type.name());
		parcel.writeInt(this.change);
		parcel.writeString(this.rooms);
		parcel.writeString(this.groups);
		parcel.writeString(this.teachers);
		parcel.writeString(this.color);
		parcel.writeString(this.note);
		parcel.writeString(this.created);
		parcel.writeString(this.guid);
		parcel.writeParcelable(this.history, 0);
	}

	/**
	 * Créé une structure de données {@code Lesson}
	 */
	public static final Parcelable.Creator<Lesson> CREATOR = new Parcelable.Creator<Lesson>() {

		@Override
		public Lesson createFromParcel(Parcel in) {
			return new Lesson(in);
		}

		@Override
		public Lesson[] newArray(int size) {
			return new Lesson[size];
		}
	};

	/**
	 * Compare deux cours. Champs comparés: date, groupe, salles, enseignants et
	 * titre.
	 * 
	 * @param o
	 *            {@code Lesson} à comparer avec l'instance actuelle
	 * @return true si les deux cours sont identique, false sinon
	 */
	@Override
	public boolean equals(Object o) {
		if (o instanceof Lesson) {
			Lesson other = (Lesson) o;
			return this.date.equals(other.date)
					&& this.groups.equals(other.groups)
					&& this.rooms.equals(other.rooms)
					&& this.teachers.equals(other.teachers)
					&& this.title.equals(other.title);
		}// if
		return super.equals(o);
	}// equals(Object)

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int hashCode() {
		return this.date.hashCode();
	}// hashCode()

	/**
	 * Compare le niveau de changement d'un cours. Pas de changement (0) Gros
	 * changement (2): heure ou la salle d'un cours Petit changement (3): autres
	 * 
	 * @param o
	 *            cours
	 * @return le statut du changement (0,1,2)
	 */
	public int getLevelChange(Object o) {
		if (o instanceof Lesson) {
			Lesson other = (Lesson) o;
			if (!this.rooms.equals(other.rooms)
					|| !this.date.equals(other.date)
					|| !this.startHour.equals(other.startHour)
					|| !this.endHour.equals(other.endHour)) {
				return Lesson.BIG_CHANGE;
			} else if (!this.teachers.equals(other.teachers)
					|| !this.groups.equals(other.groups)) {
				return Lesson.LITTLE_CHANGE;
			}// if
		}// if
		return Lesson.NO_CHANGE;
	}// equals(Object)
}// class Lesson
